package com.young.shop.api.service.impl;

import com.young.shop.api.base.BaseService;
import com.young.shop.api.dao.UserMapper;
import com.young.shop.api.service.UserService;
import com.young.shop.api.utils.AssertUtil;
import com.young.shop.api.utils.Md5Util;
import com.young.shop.api.utils.UserIDBase64;
import com.young.shop.pojo.entity.Address;
import com.young.shop.pojo.entity.User;
import com.young.shop.pojo.qo.ViewsQO;
import com.young.shop.pojo.vo.UserVO;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.Map;

/**
 * @author 曾家乐
 * @version 1.0
 * @date 2021-01-08 10:26
 * 用户业务处理实现类
 */
@Service
public class UserServiceImpl extends BaseService<User, Integer> implements UserService {
    @Autowired
    private UserMapper userMapper;

    @Override
    public UserVO userLogin(String userName , String password) {
        //非空判断：用户名、密码
        checkParams(userName , password);

        //调用数据访问层，通过用户名查询用户记录，返回用户对象
        User user = userMapper.selectByUserName(userName);

        //判断用户名是否为空
        AssertUtil.isTrue(user==null,"用户名不存在！");

        //判断密码是否正确，比较前端的密码跟数据库的密码是否一样
        checkUserPassword(password,user.getPassword());
        System.out.println("判断之后");
        //访客量
        //获取当日时间
        Date d = new Date();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        String dateNowStr = sdf.format(d);
        System.out.println(dateNowStr);
        //查询当日是否有统计
        ViewsQO viewsQO = userMapper.selectViews(dateNowStr);
        System.out.println(viewsQO);
        System.out.println("1111111111111111");
        if (viewsQO!=null){
            System.out.println("date不为空");
            //如果有数据则找出之前的统计，并更新
            Integer views = viewsQO.getViews();
            views+=1;
            userMapper.updateViews(dateNowStr,views);
        }else {
            System.out.println("进入新增");
            userMapper.insertViews(dateNowStr);
        }

        //返回构建对象
        return buildUserInfo(user);
    }

    @Override
    public UserVO userRegister(User user , String code , Map codeMap , boolean check) {
        //非空判断：用户名、密码、验证码
        checkParams(user , code);

        //调用数据访问层，通过用户名查询用户记录，返回用户对象
        User selectByUserName = userMapper.selectByUserName(user.getUserName());
        User selectByEmail = userMapper.selectByEmail(user.getEmail());

        //判断用户名、邮箱是否为空
        AssertUtil.isTrue(selectByUserName != null , "用户名已注册！");
        AssertUtil.isTrue(selectByEmail != null , "邮箱已注册！");

        //判断验证码是否正确
        String oldCode = (String) codeMap.get(user.getEmail());
        AssertUtil.isTrue(!code.equals(oldCode) , "验证码不正确！");

        //将密码进行加密，存入数据库
        String encryptPassword = encryptPassword(user.getPassword());
        user.setPassword(encryptPassword);

        //判断是否有勾选
        AssertUtil.isTrue(!check , "请勾选《服务协议》！");

        //存入数据库
        userMapper.insertUser(user);

        User finallyUser = userMapper.selectByUserName(user.getUserName());
        return buildUserInfo(finallyUser);

    }

    @Override
//    @Transactional(propagation = Propagation.REQUIRED)
    public void updatePassWord(long id,String oldPwd, String newPwd, String repeatPwd) {
        // 通过用户ID查询用户记录，返回用户对象
        User user = userMapper.selectById(id);
        // 判断用户记录是否存在
        AssertUtil.isTrue(null == user, "待更新记录不存在！");

        // 参数校验
        checkPasswordParams(user, oldPwd, newPwd, repeatPwd);

        // 设置用户的新密码
        user.setPassword(Md5Util.encode(newPwd));

        // 执行更新，判断受影响的行数
        AssertUtil.isTrue(userMapper.updatePassword(user) != 1, "修改密码失败！");
    }

    private void checkPasswordParams(User user , String oldPwd , String newPwd , String repeatPwd) {
        //判断原密码是否为空
        AssertUtil.isTrue(StringUtils.isBlank(oldPwd),"请输入原密码！");
        //判断新密码是否为空
        AssertUtil.isTrue(StringUtils.isBlank(newPwd),"请输入要修改的密码！");
        //判断重复密码是否为空
        AssertUtil.isTrue(StringUtils.isBlank(repeatPwd),"请输入重复密码！");

        //判断原密码是否相同
        AssertUtil.isTrue(!Md5Util.encode(oldPwd).equals(user.getPassword()),"输入的原密码错误！");
        //判断两次的重复是否相同
        AssertUtil.isTrue(!newPwd.equals(repeatPwd),"输入的两次密码不一致！");

    }

    @Override
    public void userAddress(Address address) {
        //非空判断
        checkParams(address);

        //判断地址数据库 是否有一样的地址信息
        checkSame(address,"设置的地址信息已保存");

        //调用dao层，通过userId，插入一条地址信息
        userMapper.insertAddress(address);

    }

    private void checkSame(Address address , String msg) {
        List<Address> addresses = userMapper.selectAddressByUserId(address.getUserId());
        addresses.forEach(item->{
            AssertUtil.isTrue(item.equals(address),msg);
        });
    }

    @Override
    public List showAddressList(long userId) {
        List<Address> addressList = userMapper.selectAddressByUserId(userId);
        return addressList;
    }

    @Override
    public void delAdd(long userId, long id) {
        AssertUtil.isTrue(userMapper.selectById(userId)==null,"请先登录！");
        AssertUtil.isTrue(userMapper.delAddress(id)!=1,"删除失败！");
    }

    @Override
    public UserVO showInformation(long id) {
        User user1 = userMapper.selectById(id);
        UserVO userVO = buildUserInfo(user1);
        return userVO;
    }

    @Override
    public void updateInformation(User user) {
        System.out.println("进入updateInformation:"+user);
        AssertUtil.isTrue(userMapper.updateUserById(user)!=1,"修改失败");
    }

    @Override
    public void updateAddress(Address address) {
        //非空判断
        checkParams(address);
        //检查修改的信息 是否一样
        checkSame(address,"未作修改");
        //修改地址数据库信息
        AssertUtil.isTrue(userMapper.updateAddress(address)!=1,"修改失败，请重新修改！");
    }

    @Override
    public Address selectAddressById(long id) {
        Address address = userMapper.selectAddressById(id);
        return address;
    }


    /**
     * 非空判断的重载
     * @param address   地址信息
     */
    private void checkParams(Address address) {
        AssertUtil.isTrue(StringUtils.isBlank(address.getName()), "请填收件姓名！");
        AssertUtil.isTrue(StringUtils.isBlank(address.getPhone()), "请填手机号码！");
        AssertUtil.isTrue(StringUtils.isBlank(address.getProvince()), "请填省！");
        AssertUtil.isTrue(StringUtils.isBlank(address.getCity()), "请填市！");
        AssertUtil.isTrue(StringUtils.isBlank(address.getDist()), "请填区/县！");
        AssertUtil.isTrue(StringUtils.isBlank(address.getAddress()), "请填详细地址！");
    }

    /**
     * 对密码进行加密
     *
     * @param password
     * @return
     */
    private String encryptPassword(String password) {
        password = Md5Util.encode(password);
        return password;
    }

    /**
     * 非空判断 重载
     *
     * @param user
     * @param code
     */
    private void checkParams(User user , String code) {
        checkParams(user.getUserName() , user.getPassword());
        AssertUtil.isTrue(StringUtils.isBlank(user.getEmail()) , "邮箱为空！");
        AssertUtil.isTrue(StringUtils.isBlank(code) , "验证码为空！");
    }

    /**
     * 构建需要返回给前端的用户对象
     *
     * @param user
     */
    private UserVO buildUserInfo(User user) {
        UserVO userVO = new UserVO();

        // 设置加密的用户ID
        //userVO.setId(UserIDBase64.decoderUserID(String.valueOf(user.getId())));

        userVO.setId(user.getId());
        userVO.setUserName(user.getUserName());
        userVO.setTrueName(user.getRealName());
        userVO.setEmail(user.getEmail());
        userVO.setPhone(user.getPhone());
        userVO.setNickName(user.getNickName());
        userVO.setBirthday(user.getBirthday());
        userVO.setSex(user.getSex());
        return userVO;
    }

    /**
     * 密码判断
     * <p>
     * 先将前端传过来的密码加密，然后再跟数据库的密码对比
     *
     * @param pwd      前端密码
     * @param password 数据库密码
     */
    private void checkUserPassword(String pwd , String password) {
        //先将前端的密码进行加密
        pwd = Md5Util.encode(pwd);
        //判断密码是否相同
        AssertUtil.isTrue(!pwd.equals(password) , "密码不正确！");
    }

    /**
     * 非空判断
     *
     * @param userName
     * @param password
     */
    private void checkParams(String userName , String password) {

        //验证用户名是否为空
        AssertUtil.isTrue(StringUtils.isBlank(userName) , "用户名为空！");
        //验证密码
        AssertUtil.isTrue(StringUtils.isBlank(password) , "密码为空！");

    }
}
